2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "AIListCell.h"
18 #import "AIListGroup.h"
19 #import "AIListObject.h"
20 #import "AIListOutlineView.h"
21 #import <AIUtilities/AIAttributedStringAdditions.h>
22 #import <AIUtilities/AIMutableOwnerArray.h>
23 #import <AIUtilities/AIParagraphStyleAdditions.h>
25 //#define ORDERING_DEBUG
27 @implementation AIListCell
29 static NSMutableParagraphStyle *leftParagraphStyleWithTruncatingTail = nil;
34 if((self = [super init]))
45 font = [[NSFont systemFontOfSize:12] retain];
46 textColor = [[NSColor blackColor] retain];
47 invertedTextColor = [[NSColor whiteColor] retain];
49 useAliasesAsRequested = YES;
51 if(!leftParagraphStyleWithTruncatingTail){
52 leftParagraphStyleWithTruncatingTail = [[NSMutableParagraphStyle styleWithAlignment:NSLeftTextAlignment
53 lineBreakMode:NSLineBreakByTruncatingTail] retain];
61 - (id)copyWithZone:(NSZone *)zone
63 AIListCell *newCell = [super copyWithZone:zone];
65 newCell->listObject = nil;
66 [newCell setListObject:listObject];
74 [invertedTextColor release];
83 //Set the list object being drawn
84 - (void)setListObject:(AIListObject *)inObject
86 if(inObject != listObject){
88 listObject = [inObject retain];
90 isGroup = [listObject isKindOfClass:[AIListGroup class]];
97 //Set our control view (Better than passing this around like crazy)
98 - (void)setControlView:(AIListOutlineView *)inControlView
100 controlView = inControlView;
104 //Display options ------------------------------------------------------------------------------------------------------
105 #pragma mark Display options
106 //Font used to display label
107 - (void)setFont:(NSFont *)inFont
111 font = [inFont retain];
114 //Calculate and cache the height of this font
115 labelFontHeight = [NSAttributedString stringHeightForAttributes:[NSDictionary dictionaryWithObject:[self font] forKey:NSFontAttributeName]];
121 //Alignment of label text
122 - (void)setTextAlignment:(NSTextAlignment)inAlignment
124 textAlignment = inAlignment;
126 - (NSTextAlignment)textAlignment{
127 return(textAlignment);
131 - (void)setTextColor:(NSColor *)inColor
133 if(inColor != textColor){
135 textColor = [inColor retain];
138 - (NSColor *)textColor{
142 - (void)setInvertedTextColor:(NSColor *)inColor
144 if(inColor != invertedTextColor){
145 [invertedTextColor release];
146 invertedTextColor = [inColor retain];
149 - (NSColor *)invertedTextColor{
150 return(invertedTextColor);
154 //Cell sizing and padding ----------------------------------------------------------------------------------------------
155 #pragma mark Cell sizing and padding
156 //Default cell size just contains our padding and spacing
159 return(NSMakeSize(0, [self topSpacing] + [self topPadding] + [self bottomPadding] + [self bottomSpacing]));
164 return([self leftSpacing] + [self leftPadding] + [self rightPadding] + [self rightSpacing]);
167 //User-defined spacing offsets. A cell may adjust these values to to obtain a more desirable default.
168 //These are offsets, they may be negative! Spacing is the distance between cells (Spacing gaps are not filled).
169 - (void)setSplitVerticalSpacing:(int)inSpacing{
170 topSpacing = inSpacing / 2;
171 bottomSpacing = (inSpacing + 1) / 2;
173 - (void)setTopSpacing:(int)inSpacing{
174 topSpacing = inSpacing;
179 - (void)setBottomSpacing:(int)inSpacing{
180 bottomSpacing = inSpacing;
182 - (int)bottomSpacing{
183 return(bottomSpacing);
185 - (void)setLeftSpacing:(int)inSpacing{
186 leftSpacing = inSpacing;
191 - (void)setRightSpacing:(int)inSpacing{
192 rightSpacing = inSpacing;
195 return(rightSpacing);
198 //User-defined padding offsets. A cell may adjust these values to to obtain a more desirable default.
199 //These are offsets, they may be negative! Padding is the distance between cell edges and their content.
200 - (void)setSplitVerticalPadding:(int)inPadding{
201 topPadding = inPadding / 2;
202 bottomPadding = (inPadding + 1) / 2;
204 - (void)setTopPadding:(int)inPadding{
205 topPadding = inPadding;
207 - (void)setBottomPadding:(int)inPadding{
208 bottomPadding = inPadding;
213 - (int)bottomPadding{
214 return(bottomPadding);
216 - (void)setLeftPadding:(int)inPadding{
217 leftPadding = inPadding;
222 - (void)setRightPadding:(int)inPadding{
223 rightPadding = inPadding;
226 return(rightPadding);
230 //Drawing --------------------------------------------------------------------------------------------------------------
233 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)inControlView{
234 [self drawInteriorWithFrame:cellFrame inView:inControlView];
236 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)inControlView
240 cellFrame.origin.y += [self topSpacing];
241 cellFrame.size.height -= [self bottomSpacing] + [self topSpacing];
242 cellFrame.origin.x += [self leftSpacing];
243 cellFrame.size.width -= [self rightSpacing] + [self leftSpacing];
245 [self drawBackgroundWithFrame:cellFrame];
248 cellFrame.origin.y += [self topPadding];
249 cellFrame.size.height -= [self bottomPadding] + [self topPadding];
250 cellFrame.origin.x += [self leftPadding];
251 cellFrame.size.width -= [self rightPadding] + [self leftPadding];
253 [self drawContentWithFrame:cellFrame];
257 //Custom highlighting (This is a private cell method we're overriding that handles selection drawing)
258 - (void)_drawHighlightWithFrame:(NSRect)cellFrame inView:(NSView *)inControlView
261 cellFrame.origin.y += [self topSpacing];
262 cellFrame.size.height -= [self bottomSpacing] + [self topSpacing];
263 cellFrame.origin.x += [self leftSpacing];
264 cellFrame.size.width -= [self rightSpacing] + [self leftSpacing];
266 [self drawSelectionWithFrame:cellFrame];
270 - (void)drawSelectionWithFrame:(NSRect)rect
275 //Draw the background of our cell
276 - (void)drawBackgroundWithFrame:(NSRect)rect
281 //Draw content of our cell
282 - (void)drawContentWithFrame:(NSRect)rect
284 [self drawDisplayNameWithFrame:rect];
287 //Draw our display name
288 - (NSRect)drawDisplayNameWithFrame:(NSRect)inRect
290 NSAttributedString *displayName = [[NSAttributedString alloc] initWithString:[self labelString]
291 attributes:[self labelAttributes]];
292 NSSize nameSize = [displayName size];
293 NSRect rect = inRect;
295 if(nameSize.width > rect.size.width) nameSize.width = rect.size.width;
296 if (nameSize.height > rect.size.height) nameSize.height = rect.size.height;
299 switch([self textAlignment]){
300 case NSCenterTextAlignment:
301 rect.origin.x += (rect.size.width - nameSize.width) / 2.0;
303 case NSRightTextAlignment:
304 rect.origin.x += (rect.size.width - nameSize.width);
310 //Draw (centered vertical)
311 int half = ceil((rect.size.height - labelFontHeight) / 2.0);
312 [displayName drawInRect:NSMakeRect(rect.origin.x,
313 rect.origin.y + half,
316 [displayName release];
318 //Adjust the drawing rect
319 switch([self textAlignment]){
320 case NSRightTextAlignment:
321 inRect.size.width -= nameSize.width;
323 case NSLeftTextAlignment:
324 inRect.origin.x += nameSize.width;
325 inRect.size.width -= nameSize.width;
335 //Display string for our list object
336 - (NSString *)labelString
338 NSString *leftText = [[listObject displayArrayForKey:@"Left Text"] objectValue];
339 NSString *rightText = [[listObject displayArrayForKey:@"Right Text"] objectValue];
342 #ifdef ORDERING_DEBUG
343 rightText = (rightText ?
344 [rightText stringByAppendingFormat:@" %f",[listObject orderIndex]] :
345 [NSString stringWithFormat:@" %f",[listObject orderIndex]]);
348 if(!leftText && !rightText){
349 return((useAliasesAsRequested ?
350 [listObject longDisplayName] :
351 ([listObject formattedUID] ? [listObject formattedUID] : [listObject longDisplayName])));
353 //Combine left text, the object name, and right text
354 return([NSString stringWithFormat:@"%@%@%@",
355 (leftText ? leftText : @""),
356 (useAliasesAsRequested ? [listObject longDisplayName] : ([listObject formattedUID] ?
357 [listObject formattedUID] :
358 [listObject longDisplayName])),
359 (rightText ? rightText : @"")]);
363 - (void)setUseAliasesAsRequested:(BOOL)inFlag
365 useAliasesAsRequested = inFlag;
368 //Attributes for displaying the label string
369 - (NSDictionary *)labelAttributes
371 NSMutableDictionary *labelAttributes;
372 NSDictionary *additionalAttributes = [self additionalLabelAttributes];
373 NSColor *currentTextColor = ([self cellIsSelected] ? [self invertedTextColor] : [self textColor]);
375 [leftParagraphStyleWithTruncatingTail setMaximumLineHeight:(float)labelFontHeight];
377 if (additionalAttributes){
378 labelAttributes = [NSMutableDictionary dictionaryWithObjectsAndKeys:
379 currentTextColor, NSForegroundColorAttributeName,
380 leftParagraphStyleWithTruncatingTail, NSParagraphStyleAttributeName,
381 [self font], NSFontAttributeName,
383 [labelAttributes addEntriesFromDictionary:additionalAttributes];
386 labelAttributes = (NSMutableDictionary *)[NSDictionary dictionaryWithObjectsAndKeys:
387 currentTextColor, NSForegroundColorAttributeName,
388 leftParagraphStyleWithTruncatingTail, NSParagraphStyleAttributeName,
389 [self font], NSFontAttributeName,
393 return(labelAttributes);
396 //Additional attributes to apply to our label string (For Sub-Classes)
397 - (NSDictionary *)additionalLabelAttributes
402 //YES if our cell is currently selected
403 - (BOOL)cellIsSelected
405 return([self isHighlighted] &&
406 [[controlView window] isKeyWindow] &&
407 [[controlView window] firstResponder] == controlView);
410 //YES if a grid would be visible behind this cell (needs to be drawn)
411 - (BOOL)drawGridBehindCell
416 //The background color for this cell. This will either be [controlView backgroundColor] or [controlView alternatingGridColor]
417 - (NSColor *)backgroundColor
419 //We could just call backgroundColorForRow: but it's best to avoid doing a rowForItem lookup if there is no grid
420 if([controlView drawsAlternatingRows]){
421 return([controlView backgroundColorForRow:[controlView rowForItem:listObject]]);
423 return([controlView backgroundColor]);